package com.zx.练习题._2022面试题收集;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * 10个线程读取10个文件中包含字符‘a’的个数
 */
public class Demo2 {

    /**
     * 普通io
     *
     * @param args
     */
    public static void main2(String[] args) {
        int size = 10;
        ExecutorService pool = Executors.newFixedThreadPool(size);
        List<String> filePaths = Arrays.asList(
                "D:\\logs\\1.txt", "D:\\logs\\2.txt");

        List<Future<Integer>> resList = new ArrayList();
        for (String filePath : filePaths) {
            Future<Integer> future = pool.submit(() -> {
                int counter = 0;
                try (FileReader fileReader = new FileReader(new File(filePath))) {
                    char[] chars = new char[1024];
                    int len = 0;
                    while ((len = fileReader.read(chars)) != -1) {
                        for (int i = 0; i < len; i++) {
                            if (chars[i] == 'a') {
                                counter++;
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return counter;
            });
            resList.add(future);
        }

        for (Future<Integer> future : resList) {
            try {
                System.out.println(future.get(60, TimeUnit.SECONDS));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        pool.shutdown();

    }

    /**
     * ByteBuffer的基本用法就是：
     * 初始化（allocate）
     * –> 写入数据（read / put）
     * –> 转换为写出模式（flip）
     * –> 写出数据（get）
     * –> 转换为写入模式（compact）
     * –> 写入数据（read / put）
     *
     * @param args
     */
    public static void main(String[] args) {
        FileChannel channel = null;
        try {
            channel = new FileInputStream("D:\\logs\\1.txt").getChannel();
            // 设置缓存区，allocate 从堆中申请内存，allocateDirect 从堆外申请内存
            ByteBuffer buf = ByteBuffer.allocate(1024);
            // ByteBuffer bufDirect = ByteBuffer.allocateDirect(1024);

            // 用于读取数据
            Charset charset = Charset.defaultCharset();
            int read = 0;
            StringBuilder sb = new StringBuilder();
            while ((read = channel.read(buf)) > 0) {
                // 转为写出模式
                buf.flip();
                // 获得可以读取数据的范围
                int begin = 0;
                int end = buf.limit();
                String str = charset.decode(buf).toString();
                sb.append(str);
                // 转为写入模式
                buf.compact();

            }
            System.out.println(sb.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
